#include <JavaScriptCore/JavaScript.h>
#include <iostream>
#include <unistd.h>

void report_exception(JSContextRef ctx, JSValueRef exception) {
  JSStringRef exception_str = JSValueToStringCopy(ctx, exception, NULL);
  size_t len = JSStringGetMaximumUTF8CStringSize(exception_str);
  char *buffer = static_cast<char *>(malloc(len));
  JSStringGetUTF8CString(exception_str, buffer, len);
  std::cerr << "Error: " << buffer << std::endl;
  free(buffer);
  JSStringRelease(exception_str);
}

int main() {
  JSGlobalContextRef global_ctx = JSGlobalContextCreate(NULL);
  JSContextRef ctx = global_ctx;
  const char *promise_script = 
        "new Promise(function(resolve, reject) {"
          "setTimeout(function() {"
            "resolve('Hello, World!');"
          "}, 1000);"
        "});";


  JSStringRef script = JSStringCreateWithUTF8CString(promise_script);
  JSValueRef exception = NULL;
  JSValueRef result = JSEvaluateScript(ctx, script, NULL, NULL, 0, &exception);

  if (exception) {
    report_exception(ctx, exception);
    JSGlobalContextRelease(global_ctx);
    return 1;
  }

  // 为 Promise 添加 then 和 catch 处理程序
  JSObjectRef promise = JSValueToObject(ctx, result, &exception);
  if (exception) {
    report_exception(ctx, exception);
    JSGlobalContextRelease(global_ctx);
    return 1;
  }

  JSStringRef then_str = JSStringCreateWithUTF8CString("then");
  JSStringRef catch_str = JSStringCreateWithUTF8CString("catch");
  JSObjectRef then_func =
      (JSObjectRef)JSObjectGetProperty(ctx, promise, then_str, &exception);
  JSObjectRef catch_func =
      (JSObjectRef)JSObjectGetProperty(ctx, promise, catch_str, &exception);
  JSStringRelease(then_str);
  JSStringRelease(catch_str);

  if (exception) {
    report_exception(ctx, exception);
    JSGlobalContextRelease(global_ctx);
    return 1;
  }

  JSObjectCallAsFunction(ctx, then_func, promise, 0, NULL, &exception);
  JSObjectCallAsFunction(ctx, catch_func, promise, 0, NULL, &exception);

  if (exception) {
    report_exception(ctx, exception);
    JSGlobalContextRelease(global_ctx);
    return 1;
  }

  // 等待 Promise 完成
  sleep(2);

  JSGlobalContextRelease(global_ctx);
  return 0;
}